package ferp.core.mode;

import ferp.core.ai.tree2.Evaluator;
import ferp.core.ai.tree2.Score;
import ferp.core.calc.Calculator;
import ferp.core.card.Card;
import ferp.core.game.Game;
import ferp.core.game.Input;
import ferp.core.game.Settings;
import ferp.core.game.Trick;
import ferp.core.player.Player;
import ferp.core.player.Profile;

/**
 * User: olegs
 * Date: 19/05/11 15:11
 */
public class Passing extends Moving
{
  @Override
  public int initialize(Game.Listener listener, Profile profile, Game g, Settings settings) throws Game.Error
  {
    // force game type to standing
    g.type = Game.Type.STANDING;

    return super.initialize(listener, profile, g, settings);
  }

  @Override
  public int evaluator()
  {
    return Evaluator.PASSING;
  }

  @Override
  public void score(Game g, Settings settings)
  {
    Calculator.get(settings.gameFlavor).passing(g, settings);

    // update the number of passing sets played consequentially
    ++g.consequentPassingSets;
  }

  @Override
  public Card.State getTalonCardState(Game g, Settings settings, int i)
  {
    if (settings.isRostov() || g.rounds < i)
      return Card.State.FACE_DOWN;

    if (g.rounds == i)
      return Card.State.FACE_UP;

    return super.getTalonCardState(g, settings, i);
  }

  @Override
  protected void prepare(Game.Listener listener, Game g, Settings settings)
  {
    super.prepare(listener, g, settings);

    // open next talon card
    if (g.rounds <= Game.TALON_SIZE)
    {
      if (g.rounds < Game.TALON_SIZE)
      {
        // add talon card to trick and fire event if not Rostov
        if (!settings.isRostov())
        {
          g.trick.current = Trick.add(g.trick.current, g.getTalonCompressed(g.rounds));
          listener.onTalonCardPlayed(settings, g.rounds);
        }
      }

      // adjust starting player
      if (!settings.isRostov())
        g.player.starting = Game.next(g.player.dealer);
    }
  }

  @Override
  protected Act act(Game.Listener listener, Game g, Settings settings, Input input) throws Game.Error
  {
    switch (input.offer)
    {
      case REST_TRICKS_ARE_MINE:
        // score is relative => number of rounds to play has to be equal or greater than score
        int rest = Game.MAXIMUM_ROUNDS - g.rounds;

        if (rest >= Score.get((short)input.score, g.player.current))
        {
          g.addTricks(g.player.current, rest);

          return Act.DONE;
        }

        listener.onOfferDeclined();

        return Act.STAY;

      case NO_MORE_TRICKS:
        // score is relative => it must be equal to 0
        int score = Score.get((short)input.score, g.player.current);

        if (score == 0)
        {
          // assign correct number of remaining tricks to other players
          int p2 = Game.next(g.player.current);
          int p3 = Game.next(p2);

          g.addTricks(p2, Score.get((short)input.score, p2));
          g.addTricks(p3, Score.get((short)input.score, p3));

          return Act.DONE;
        }

        listener.onOfferDeclined();

        return Act.STAY;
    }

    return super.act(listener, g, settings, input);
  }

  @Override
  protected void setMoverInputOptions(Game.Listener listener, Game g, Player mover) throws Game.Error
  {
    mover.setPassingInputOptions(listener, g);
  }
}
